home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / programer2 / icon / Source / Icont / C / Lsym < prev    next >
Encoding:
Text File  |  1990-07-20  |  9.5 KB  |  421 lines

  1. /*
  2.  * lsym.c -- functions for symbol table manipulation.
  3.  */
  4.  
  5. #include "../h/config.h"
  6. #include "link.h"
  7. #include "general.h"
  8. #include "tproto.h"
  9. #include "globals.h"
  10.  
  11. /*
  12.  * Prototypes.
  13.  */
  14.  
  15. hidden struct     fentry *alcfhead
  16.    Params((struct fentry *blink,char *name, int fid, struct rentry *rlist));
  17. hidden struct     rentry *alcfrec    
  18.    Params((struct rentry *link,int rnum, int fnum));
  19. hidden struct     gentry *alcglobal
  20.    Params((struct gentry *blink,char *name, int flag,int nargs,int procid));
  21. hidden struct     ientry *alcident    Params((char *nam,int len));
  22.  
  23. int dynoff;            /* stack offset counter for locals */
  24. int argoff;            /* stack offset counter for arguments */
  25. int static1;            /* first static in procedure */
  26. int lstatics = 0;        /* static variable counter */
  27.  
  28. int nlocal;            /* number of locals in local table */
  29. int nconst;            /* number of constants in constant table */
  30. int nfields = 0;        /* number of fields in field table */
  31.  
  32. /*
  33.  * instid - copy the string s to the start of the string free space
  34.  *  and call putident with the length of the string.
  35.  */
  36. char *instid(s)
  37. char *s;
  38.    {
  39.    register int l;
  40.    register char *p1, *p2;
  41.  
  42.    p1 = lsfree;
  43.    p2 = s;
  44.    l = 0;
  45.    do {
  46.       if (p1 > lsend)
  47.          quit("out of string space");
  48.       l++;
  49.       } while (*p1++ = *p2++);
  50.    return putident(l);
  51.    }
  52.  
  53. /*
  54.  * putident - install the identifier named by the string starting at lsfree
  55.  *  and extending for len bytes.  The installation entails making an
  56.  *  entry in the identifier hash table and then making an identifier
  57.  *  table entry for it with alcident.  A side effect of installation
  58.  *  is the incrementing of lsfree by the length of the string, thus
  59.  *  "saving" it.
  60.  *
  61.  * Nothing is changed if the identifier has already been installed.
  62.  */
  63. char *putident(len)
  64. int len;
  65.    {
  66.    register int hash;
  67.    register char *s;
  68.    register struct ientry *ip;
  69.    int l;
  70.  
  71.    /*
  72.     * Compute hash value by adding bytes and masking result with imask.
  73.     *  (Recall that imask is ihsize-1.)
  74.     */
  75.    s = lsfree;
  76.    hash = 0;
  77.    l = len;
  78.    while (l--)
  79.       hash += *s++;
  80.    l = len;
  81.    s = lsfree;
  82.    hash &= imask;
  83.    /*
  84.     * If the identifier hasn't been installed, install it.
  85.     */
  86.    if ((ip = lihash[hash]) != NULL) {     /* collision */
  87.       for (;;) { /* work down i_blink chain until id is found or the
  88.                      end of the chain is reached */
  89.          if (l == ip->i_length && lexeql(l, s, ip->i_name))
  90.             return (ip->i_name); /* id is already installed, return it */
  91.          if (ip->i_blink == NULL) { /* end of chain */
  92.             ip->i_blink = alcident(s, l);
  93.             lsfree += l;
  94.             return s;
  95.             }
  96.          ip = ip->i_blink;
  97.          }
  98.       }
  99.    /*
  100.     * Hashed to an empty slot.
  101.     */
  102.    lihash[hash] = alcident(s, l);
  103.    lsfree += l;
  104.    return s;
  105.    }
  106.  
  107. /*
  108.  * lexeql - compare two strings of given length.  Returns non-zero if
  109.  *  equal, zero if not equal.
  110.  */
  111. int lexeql(l, s1, s2)
  112. register int l;
  113. register char *s1, *s2;
  114.    {
  115.    while (l--)
  116.       if (*s1++ != *s2++)
  117.          return 0;
  118.    return 1;
  119.    }
  120.  
  121. /*
  122.  * alcident - get the next free identifier table entry, and fill it in with
  123.  *  the specified values.
  124.  */
  125. static struct ientry *alcident(nam, len)
  126. char *nam;
  127. int len;
  128.    {
  129.    register struct ientry *ip;
  130.  
  131.    if (lifree >= &litable[isize])
  132.       quit("out of identifier table space");
  133.    ip = lifree++;
  134.    ip->i_blink = NULL;
  135.    ip->i_name = nam;
  136.    ip->i_length = len;
  137.    return ip;
  138.    }
  139.  
  140. /*
  141.  * locinit -  clear local symbol table.
  142.  */
  143. novalue locinit()
  144.    {
  145.    dynoff = 0;
  146.    argoff = 0;
  147.    nlocal = -1;
  148.    nconst = -1;
  149.    static1 = lstatics;
  150.    }
  151.  
  152. /*
  153.  * putlocal - make a local symbol table entry.
  154.  */
  155. novalue putlocal(n, id, flags, imperror, procname)
  156. int n;
  157. char *id;
  158. register int flags;
  159. int imperror;
  160. char *procname;
  161.    {
  162.    register struct lentry *lp;
  163.    union {
  164.       struct gentry *gp;
  165.       int bn;
  166.       } p;
  167.  
  168.    if (n >= lsize)
  169.       quit("out of local symbol table space");
  170.    if (n > nlocal)
  171.       nlocal = n;
  172.    lp = &lltable[n];
  173.    lp->l_name = id;
  174.    lp->l_flag = flags;
  175.    if (flags == 0) {                /* undeclared */
  176.       if ((p.gp = glocate(id)) != NULL) {    /* check global */
  177.          lp->l_flag = F_Global;
  178.          lp->l_val.global = p.gp;
  179.          }
  180.  
  181.       else if ((p.bn = blocate(id)) != 0) {    /* check for function */
  182.          lp->l_flag = F_Builtin;
  183.          lp->l_val.global = putglobal(id, F_Builtin | F_Proc, -1, p.bn);
  184.          }
  185.  
  186.       else {                    /* implicit local */
  187.          if (imperror)
  188.             lwarn(id, "undeclared identifier, procedure ", procname);
  189.          lp->l_flag = F_Dynamic;
  190.          lp->l_val.offset = ++dynoff;
  191.          }
  192.       }
  193.    else if (flags & F_Global) {            /* global variable */
  194.       if ((p.gp = glocate(id)) == NULL)
  195.          quit("putlocal: global not in global table");
  196.       lp->l_val.global = p.gp;
  197.       }
  198.    else if (flags & F_Argument)            /* procedure argument */
  199.       lp->l_val.offset = ++argoff;
  200.    else if (flags & F_Dynamic)            /* local dynamic */
  201.       lp->l_val.offset = ++dynoff;
  202.    else if (flags & F_Static)            /* local static */
  203.       lp->l_val.staticid = ++lstatics;
  204.    else
  205.       quit("putlocal: unknown flags");
  206.    }
  207.  
  208. /*
  209.  * putglobal - make a global symbol table entry.
  210.  */
  211. struct gentry *putglobal(id, flags, nargs, procid)
  212. char *id;
  213. int flags;
  214. int nargs;
  215. int procid;
  216.    {
  217.    register struct gentry *p;
  218.  
  219.    if ((p = glocate(id)) == NULL) {    /* add to head of hash chain */
  220.       p = lghash[ghasher(id)];
  221.       lghash[ghasher(id)] = alcglobal(p, id, flags, nargs, procid);
  222.       return lghash[ghasher(id)];
  223.       }
  224.    p->g_flag |= flags;
  225.    p->g_nargs = nargs;
  226.    p->g_procid = procid;
  227.    return p;
  228.    }
  229.  
  230. /*
  231.  * putconst - make a constant symbol table entry.
  232.  */
  233. novalue putconst(n, flags, len, pc, valp)
  234. int n;
  235. int flags, len;
  236. word pc;
  237. union xval *valp;
  238.  
  239.    {
  240.    register struct centry *p;
  241.    if (n >= csize)
  242.       quit("out of constant table space");
  243.    if (nconst < n)
  244.       nconst = n;
  245.    p = &lctable[n];
  246.    p->c_flag = flags;
  247.    p->c_pc = pc;
  248.    if (flags & F_IntLit) {
  249.       p->c_val.ival = valp->ival;
  250.       }
  251.    else if (flags & F_StrLit) {
  252.       p->c_val.sval = valp->sval;
  253.       p->c_length = len;
  254.       }
  255.    else if (flags & F_CsetLit) {
  256.       p->c_val.sval = valp->sval;
  257.       p->c_length = len;
  258.       }
  259.    else    if (flags & F_RealLit)
  260.  
  261. #ifdef Double
  262. /* access real values one word at a time */
  263.     {  int *rp, *rq;    
  264.        rp = (int *) &(p->c_val.rval);
  265.        rq = (int *) &(valp->rval);
  266.        *rp++ = *rq++;
  267.        *rp   = *rq;
  268.     }
  269. #else                    /* Double */
  270.       p->c_val.rval = valp->rval;
  271. #endif                    /* Double */
  272.  
  273.    else
  274.       fprintf(stderr, "putconst: bad flags: %06o %011lo\n", flags, valp->ival);
  275.    }
  276.  
  277. /*
  278.  * putfield - make a record/field table entry.
  279.  */
  280. novalue putfield(fname, rnum, fnum)
  281. char *fname;
  282. int rnum, fnum;
  283.    {
  284.    register struct fentry *fp;
  285.    register struct rentry *rp, *rp2;
  286.    word hash;
  287.  
  288.    fp = flocate(fname);
  289.    if (fp == NULL) {        /* create a field entry */
  290.       nfields++;
  291.       hash = fhasher(fname);
  292.       fp = lfhash[hash];
  293.       lfhash[hash] = alcfhead(fp, fname, nfields, alcfrec((struct rentry *)NULL,
  294.          rnum, fnum));
  295.       return;
  296.       }
  297.    rp = fp->f_rlist;        /* found field entry, look for */
  298.    if (rp->r_recid > rnum) {    /*   spot in record list */
  299.       fp->f_rlist = alcfrec(rp, rnum, fnum);
  300.       return;
  301.       }
  302.    while (rp->r_recid < rnum) {    /* keep record list ascending */
  303.       if (rp->r_link == NULL) {
  304.          rp->r_link = alcfrec((struct rentry *)NULL, rnum, fnum);
  305.          return;
  306.          }
  307.       rp2 = rp;
  308.       rp = rp->r_link;
  309.       }
  310.    rp2->r_link = alcfrec(rp, rnum, fnum);
  311.    }
  312.  
  313. /*
  314.  * glocate - lookup identifier in global symbol table, return NULL
  315.  *  if not present.
  316.  */
  317. struct gentry *glocate(id)
  318. char *id;
  319.    {
  320.    register struct gentry *p;
  321.  
  322.    p = lghash[ghasher(id)];
  323.    while (p != NULL && p->g_name != id)
  324.       p = p->g_blink;
  325.    return p;
  326.    }
  327.  
  328. /*
  329.  * flocate - lookup identifier in field table.
  330.  */
  331. struct fentry *flocate(id)
  332. char *id;
  333.    {
  334.    register struct fentry *p;
  335.  
  336.    p = lfhash[fhasher(id)];
  337.    while (p != NULL && p->f_name != id)
  338.       p = p->f_blink;
  339.    return p;
  340.    }
  341.  
  342. /*
  343.  * alcglobal - create a new global symbol table entry.
  344.  */
  345. static struct gentry *alcglobal(blink, name, flag, nargs, procid)
  346. struct gentry *blink;
  347. char *name;
  348. int flag;
  349. int nargs;
  350. int procid;
  351.    {
  352.    register struct gentry *gp;
  353.  
  354.    if (lgfree >= &lgtable[gsize])
  355.       quit("out of global symbol table space");
  356.    gp = lgfree++;
  357.    gp->g_blink = blink;
  358.    gp->g_name = name;
  359.    gp->g_flag = flag;
  360.    gp->g_nargs = nargs;
  361.    gp->g_procid = procid;
  362.    return gp;
  363.    }
  364.  
  365. /*
  366.  * alcfhead - allocate a field table header.
  367.  */
  368. static struct fentry *alcfhead(blink, name, fid, rlist)
  369. struct fentry *blink;
  370. char *name;
  371. int fid;
  372. struct rentry *rlist;
  373.    {
  374.    register struct fentry *fp;
  375.  
  376.    if (lffree >= &lftable[fsize])
  377.       quit("out of field table space");
  378.    fp = lffree++;
  379.    fp->f_blink = blink;
  380.    fp->f_name = name;
  381.    fp->f_fid = fid;
  382.    fp->f_rlist = rlist;
  383.    return fp;
  384.    }
  385.  
  386. /*
  387.  * alcfrec - allocate a field table record list element.
  388.  */
  389. static struct rentry *alcfrec(link, rnum, fnum)
  390. struct rentry *link;
  391. int rnum, fnum;
  392.    {
  393.    register struct rentry *rp;
  394.  
  395.    if (lrfree >= &lrtable[rsize])
  396.       quit("out of field table space for record lists");
  397.    rp = lrfree++;
  398.    rp->r_link = link;
  399.    rp->r_recid = rnum;
  400.    rp->r_fnum = fnum;
  401.    return rp;
  402.    }
  403.  
  404. /*
  405.  * blocate - search for a function. The search is linear to make
  406.  *  it easier to add/delete functions. If found, returns index+1 for entry.
  407.  */
  408.  
  409. int blocate(s)
  410. register char *s;
  411.    {
  412.    register int i;
  413.    extern char *ftable[];
  414.    extern int ftbsize;
  415.  
  416.    for (i = 0; i < ftbsize; i++)
  417.       if (strcmp(ftable[i], s) == 0)
  418.      return i + 1;
  419.    return 0;
  420.    }
  421.